package wsepForum.ui.jaxcent;
import java.util.Map;

import jaxcent.HtmlDiv;
import jaxcent.HtmlElement;
import jaxcent.JaxcentPage;
import jaxcent.Jaxception;
import jaxcentPlus.JaxcentSessionListener;
import wsepForum.common.elements.Section;
import wsepForum.common.elements.User.UserType;
import wsepForum.domain.ISessionObserver;
import wsepForum.domain.Session;
import wsepForum.domain.SessionManager;
import wsepForum.domain.exceptions.UnAuthorizedException;
import wsepForum.domain.exceptions.WrongPasswordException;
import wsepForum.domain.handlers.MemberHandler;
import wsepForum.persistance.exceptions.DataBaseIOException;
import wsepForum.persistance.exceptions.WrongUserNameException;
import wsepForum.ui.jaxcent.states.IXState;
import wsepForum.ui.jaxcent.states.XEditor;
import wsepForum.ui.jaxcent.states.XLogin;
import wsepForum.ui.jaxcent.states.XSearchQuery;
import wsepForum.ui.jaxcent.states.XSection;
import wsepForum.ui.jaxcent.states.XSectionCreate;
import wsepForum.ui.jaxcent.states.XSectionEdit;
import wsepForum.ui.jaxcent.states.XStatsQuery;
import wsepForum.ui.jaxcent.states.XTopic;
import wsepForum.ui.jaxcent.states.XUserEditDetails;
import wsepForum.ui.jaxcent.states.XUserRegister;
import wsepForum.ui.jaxcent.states.IXState.StateType;
import wsepForum.ui.jaxcent.states.XEditor.ActionType;
/**
 * The class that connects the displayed user web page to the system
 * @author Oren
 *
 */
public class XMain extends JaxcentPage implements ISessionObserver, IXContext {
	/**
	 * the connected user type
	 */
	private UserType userType;
	/**
	 * the connected user name
	 */
	private String userName;
	/**
	 * the domain's session connected to this page
	 */
	private Session session;
	/**
	 * the current section
	 */
	private int currentSection;
	/**
	 * the inner state(page)
	 */
	private IXState state;
	/**
	 * jaxcent elements
	 */
	private HtmlDiv xBody;
	private HtmlElement xLogin;
	private HtmlElement xLogout;
	private HtmlElement xRegister;
	private HtmlElement xDetails;
	private HtmlElement xStats;
	private HtmlElement xSection;

	/*****************************
	 * CONSTRUCTOR               *
	 *****************************/
	public XMain() {
		extractSession();
		initPanel();
		setUser();
		this.state = null;
		this.currentSection = 0;
		loadPage();
	}

	/*****************************
	 * METHODS                   *
	 *****************************/

	/**
	 * load the page using the url address
	 */
	private void loadPage() {
		try {
			String[] url = getCurrentPath().split("\\?");
			if (url.length == 1)
				loadSection(0);
			else {
				url = url[1].split("\\.");
				switch (url.length) {
				case 2:
					if (url[0].equalsIgnoreCase("topic"))
						loadTopic(Integer.valueOf(url[1]),0);
					else if (url[0].equalsIgnoreCase("section"))
						loadSection(Integer.valueOf(url[1]));
					else if (url[0].equalsIgnoreCase("search"))
						loadSearch();
					else if (url[0].equalsIgnoreCase("stats")) {
						UserType type = getUserType();
						if (type == UserType.MODERATOR | type ==  UserType.ADMIN) {
							loadStats();
						} else {
							loadSection(0);
						}
					}
					else
						loadSection(0);
					break;
				case 3:
					if (url[0].equalsIgnoreCase("topic"))
						loadTopic(Integer.valueOf(url[1]),Integer.valueOf(url[2]));
					else
						loadSection(0);
					break;
				default:
					loadSection(0);
					break;
				}
			}
		} catch (NumberFormatException e) {
			loadSection(0);
		}
	}

	/**
	 * get the currect session from the domain / or register new session
	 */
	@SuppressWarnings("unchecked")
	private void extractSession() {
		final String KEY = "domainsession";
		Session session = null;
		try {
			Map<Object,Object> xsessionMap = (Map<Object,Object>)getAllSessionData(false);
			session = (Session)xsessionMap.get(KEY);
			if (session == null) {
				session = SessionManager.getInstance().createNewSession();
				final double sessionId= session.getSessionID();
				JaxcentSessionListener listener = new JaxcentSessionListener() {
					@Override
					public void actOnSessionRemoval() {
						SessionManager.getInstance().endSession(sessionId);
					}
				};
				setSessionListener(listener);
			}
			xsessionMap.clear();
			xsessionMap.put(KEY, session);
		} catch (Jaxception e) {
			showMessageDialog("cannot load sesison data, please reload page, or try to delete cookies");
		}
		this.session = session;
	}

	/* (non-Javadoc)
	 * @see jaxcent.JaxcentPage#onLoad()
	 */
	@Override
	public void onLoad() {
		this.session.addSessionObserver(this);
	}

	/* (non-Javadoc)
	 * @see jaxcent.JaxcentPage#onUnload()
	 */
	@Override
	public void onUnload() {
		this.session.removeSessionObserver(this);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#getPage()
	 */
	@Override
	public JaxcentPage getPage() {
		return this;
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#getSession()
	 */
	@Override
	public Session getSession() {
		return this.session;
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadLogin()
	 */
	@Override
	public void loadLogin() {
		this.state = new XLogin(this);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadSection(int)
	 */
	@Override
	public void loadSection(int sectionId) {
		if (this.state != null && this.state.getType() == StateType.SECTION) {
			((XSection)this.state).loadContent(sectionId);
		}
		else {
			this.state = new XSection(this,sectionId);
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadSection(wsepForum.common.elements.Section)
	 */
	@Override
	public void loadSection(Section section) {
		if (this.state != null && this.state.getType() == StateType.SECTION) {
			((XSection)this.state).loadContent(section);
		}
		else {
			this.state = new XSection(this,section);
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadTopic(int)
	 */
	@Override
	public void loadTopic(int topicId, int msgId) {
		if (this.state != null && this.state.getType() == StateType.TOPIC) {
			((XTopic)this.state).loadContent(topicId);
		}
		else {
			if (msgId == 0)
				this.state = new XTopic(this,topicId);
			else
				this.state = new XTopic(this,topicId,msgId);
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadEditor(wsepForum.ui.jaxcent.states.XEditor.ActionType, java.lang.Object[])
	 */
	@Override
	public void loadEditor(ActionType type, Object[] parameters) {
		this.state = new XEditor(this, type, parameters);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadUserDetails()
	 */
	@Override
	public void loadUserDetails() {
		if (getUserType()==UserType.GUEST)
			this.state = new XUserRegister(this);
		else
			this.state = new XUserEditDetails(this);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadStats()
	 */
	@Override
	public void loadStats() {
		this.state = new XStatsQuery(this);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadSearch()
	 */
	@Override
	public void loadSearch() {
		this.state = new XSearchQuery(this);
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loadEditSection(wsepForum.common.elements.Section)
	 */
	@Override
	public void loadSectionControl(Section section, boolean isNew) {
		if (isNew)
			this.state = new XSectionCreate(this,section);
		else
			this.state = new XSectionEdit(this,section);
	}
	/**
	 * replace inner body area with the given text
	 * @return the xbody the new text to put in area
	 */
	@Override
	public void setBody(String newBody) {
		try {
			this.xBody.setInnerHTML(newBody);
		} catch (Jaxception e) {
			showMessageDialog("Cannot load page! please try again later.");
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.network.server.jax.pages.XContext#getUserType()
	 */
	@Override
	public UserType getUserType() {
		return this.userType;
	}


	/**
	 * change user display by its type
	 */
	private void setUser() {
		if (getSession().getLoginTime() == null) {
			this.userType = UserType.GUEST;
			this.userName = "guest";
		}
		else
		{
			this.userType = ((MemberHandler)this.getSession().getHandler()).getUser().getUserType();
			this.userName = ((MemberHandler)this.getSession().getHandler()).getUser().getUserName();
		}
		updatePanel();
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#getUserName()
	 */
	public String getUserName() {
		return this.userName;
	}

	/**
	 * update elements on the page
	 */
	private void updatePanel() {
		try {
			if (this.userType == UserType.GUEST) {
				this.xLogout.hide();
				this.xLogout.setInnerHTML("");
				this.xLogin.show();
				this.xRegister.show();
				this.xDetails.hide();
				this.xStats.hide();
			}
			else {
				if (this.userType == UserType.MEMBER) {
					this.xStats.hide();
				} else {
					this.xStats.show();
				}
				this.xLogin.hide();
				this.xLogout.setInnerHTML("["+this.userName+"] Logout");
				this.xLogout.show();
				this.xRegister.hide();
				this.xDetails.show();
			}
		} catch (Jaxception e) {
			showMessageDialog("problem with changing user state, please reload the page\n"+e.getMessage());
		}
	}


	/**
	 * initiate element on the page
	 */
	private void initPanel() {
		try {
			this.xBody = new HtmlDiv(this,"page-body");
			new HtmlElement(this,"xhome") {
				public void onClick() {
					loadSection(0);
				}
			};
			this.xSection = new HtmlElement(this,"xcursection");
			new HtmlElement(this,"xhometop") {
				public void onClick() {
					loadSection(0);
				}
			};
			this.xLogin = new HtmlElement(this,"xlogin") {
				public void onClick() {
					loadLogin();
				}
			};
			this.xLogin.setInnerHTML("Login");
			this.xLogout = new HtmlElement(this,"xlogout") {
				public void onClick() {
					logoutUser(false);
				}
			};
			this.xRegister = new HtmlElement(this,"xregister") {
				public void onClick() {
					loadUserDetails();
				}
			};
			this.xDetails = new HtmlElement(this,"xdetails") {
				public void onClick() {
					loadUserDetails();
				}
			};
			this.xStats = new HtmlElement(this,"xstats");
			new HtmlElement(this,"xstatslink")
			{
				public void onClick() {
					loadStats();
				}
			};
			new HtmlElement(this,"xsearch") {
				public void onClick() {
					loadSearch();
				}
			};
		} catch (Jaxception e) {
			this.showMessageDialog("cannot load some of the page's content, try reloading.\n"+e.getMessage());
		}
		updatePanel();
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#setSection(int, java.lang.String)
	 */
	@Override
	public void setSection(int sectionId, String sectionName) {
		if (sectionId!=this.currentSection) {
			try {
				if (sectionId==0) {
					this.currentSection = sectionId;
					this.xSection.setInnerHTML("");
				}
				else {
					String section;
					if (sectionName!=null) {
						section = sectionName;
					}
					else {
						section = getSession().getHandler().getSection(sectionId).getHeadLine();
					}
					this.currentSection = sectionId;
					this.xSection.setInnerHTML(
							"&nbsp;&raquo;&nbsp;<a id=\"xcursectionlink\">"+section+"</a>&nbsp;"+
							"<a href=\"/?section."+sectionId+"\"><img src=\"/images/icon_topic_latest.gif\" width=\"11\" height=\"9\" /></a>");
					new HtmlElement(this,"xcursectionlink") {
						public void onClick() {
							loadSection(currentSection);
						}
					};
				}
			} catch (Exception e) {/*don't update section link*/}
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#logoutUser()
	 */
	@Override
	public boolean logoutUser(boolean quietLogout) {
		if (getSession().logout()) {
			setUser();
			loadSection(0);
			if (!quietLogout) this.session.reportLocalSessionChange(this);
			return true;
		}
		else {
			if (!quietLogout) {
				showMessageDialog("Unable to logout!");
			} else {
				setUser();
				loadSection(0);
			}
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.ui.jaxcent.IXContext#loginUser(java.lang.String, java.lang.String)
	 */
	@Override
	public void loginUser(String user, String password) {
		try {
			if (getSession().login(user, password)) {
				setUser();
				loadSection(0);
				this.session.reportLocalSessionChange(this);
			}
			else {
				showMessageDialog( "Incorrect login input! please try again." );
				return;
			}
		} catch (WrongUserNameException e) {
			showMessageDialog( "Unable to login! typed wrong username" );
		return;
		} catch (UnAuthorizedException e2) {
			showMessageDialog( "Unable to login! you are not authorized to do so\ntry logging out..." );
		return;
		} catch (WrongPasswordException e3) {
			showMessageDialog( "Unable to login! you typed a wrong password" );
		return;
		} catch (DataBaseIOException e4) {
			showMessageDialog( "Unable to login! problem with our database, please try again later.." );
		return;
		} catch (Exception e) {
			showMessageDialog( "Unable to login! "+e.getMessage() );
		return;
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.domain.IDisconnectObserver#disconnect()
	 */
	@Override
	public void onLogoutDemand() {
		if (logoutUser(true)) {
			showMessageDialog("You were disconnected by the server");
		}
	}

	/* (non-Javadoc)
	 * @see wsepForum.domain.ISessionObserver#onConnect()
	 */
	@Override
	public void onLocalChange() {
		setUser();
		loadSection(0);
	}

}





